package cn.qingyun.gis.modules.building.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.qingyun.gis.modules.building.entity.BuildingGaode;
import cn.qingyun.gis.modules.building.entity.BuildingGather;
import cn.qingyun.gis.modules.building.entity.BuildingGatherInitDTO;
import cn.qingyun.gis.modules.building.entity.BuildingProofread;
import cn.qingyun.gis.modules.building.mapper.BuildingGaodeMapper;
import cn.qingyun.gis.modules.building.mapper.BuildingGatherMapper;
import cn.qingyun.gis.modules.building.service.IBuildingGatherService;
import cn.qingyun.gis.modules.building.service.IBuildingProofreadService;
import cn.qingyun.gis.modules.express.util.SyncTool;
import cn.qingyun.gis.modules.init.utils.CsvTool;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.csvreader.CsvReader;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * <p>
 * 楼宇摸排集客数据 服务实现类
 * </p>
 *
 * @author guest
 * @since 2024-04-11
 */
@Service
@Slf4j
public class BuildingGatherServiceImpl extends ServiceImpl<BuildingGatherMapper, BuildingGather> implements IBuildingGatherService {

    @Resource
    private BuildingGaodeMapper gaodeMapper;
    @Resource
    private BuildingGatherMapper gatherMapper;
    @Resource
    private IBuildingProofreadService proofreadService;

    @Override
    public void initData(MultipartFile file) {
        log.debug("BuildingGatherServiceImpl initData begin");
        CompletableFuture.runAsync(() -> {
            try {
                long startTime = System.currentTimeMillis(); //获取当前内容
                CsvReader csvReader = new CsvReader(file.getInputStream(), StandardCharsets.UTF_8);
                // 读表头
                csvReader.setSafetySwitch(false);
                csvReader.readHeaders();
                List<BuildingGatherInitDTO> imports = Lists.newArrayList();
                // 读内容
                while (csvReader.readRecord()) {
                    imports.add(CsvTool.toBean(csvReader, BuildingGatherInitDTO.class));
                }
                int batchSize = 1000; //批次处理数据量
                if (CollUtil.isNotEmpty(imports)) {
                    // 高并发导入
                    int count = imports.size();
                    int pages = (count / batchSize) + 1; // 1000条数据启动一个线程
                    DateTime date = DateUtil.date();
                    SyncTool.doSync(pages, i -> {
                        int batchNum = i == 1 ? 0 : (i - 1) * batchSize; //开始索引
                        int batchEnd = Math.min(batchNum + batchSize, count); //结束索引 = batchEnd - 1
                        List<BuildingGather> recordsBatch = Lists.newArrayList(); //存放批次数据
                        for (int j = batchNum; j < batchEnd; j++) {
                            BuildingGatherInitDTO anImport = imports.get(j);
                            BuildingGather gather = new BuildingGather();
                            BeanUtils.copyProperties(anImport, gather);
                            // 导入时间数据
                            gather.setCreateTime(date);
                            gather.setUpdateTime(date);
                            recordsBatch.add(gather);
                        }
                        this.saveBatch(recordsBatch);
                        recordsBatch.clear();
                    });
                }
                log.debug("数据解析成功，当前导入需要花费{}毫秒", System.currentTimeMillis() - startTime);
            } catch (Exception e) {
                log.error("数据解析失败", e);
            }
        });
    }

    @Override
    public void mapping() {
        CompletableFuture.runAsync(() -> {
            // 初始化勘误表
            LambdaQueryWrapper<BuildingGaode> gdQueryWapper = new LambdaQueryWrapper<>();
            List<BuildingGaode> gaodeDataList = gaodeMapper.selectList(gdQueryWapper);
            int batchSize = 1000; //批次处理数据量
            if (CollUtil.isNotEmpty(gaodeDataList)) {
                // 高并发导入
                int count = gaodeDataList.size();
                int pages = (count / batchSize) + 1; // 1000条数据启动一个线程
                DateTime date = DateUtil.date();
                SyncTool.doSync(pages, i -> {
                    int batchNum = i == 1 ? 0 : (i - 1) * batchSize; //开始索引
                    int batchEnd = Math.min(batchNum + batchSize, count); //结束索引 = batchEnd - 1
                    List<BuildingProofread> proofreadList = Lists.newArrayList(); //存放批次数据
                    for (int j = batchNum; j < batchEnd; j++) {
                        BuildingGaode buildingGaode = gaodeDataList.get(j);
                        String poiId = buildingGaode.getPoiId();
                        BuildingProofread proofread = new BuildingProofread();
                        //  根据高德的POI_ID 查询集客表  填写关联字段
                        LambdaQueryWrapper<BuildingGather> gatherQueryWapper = new LambdaQueryWrapper<>();
                        gatherQueryWapper.eq(BuildingGather::getGdPoiId, poiId);
                        List<BuildingGather> buildingGatherList = gatherMapper.selectList(gatherQueryWapper);
                        if (ObjectUtil.isNotEmpty(buildingGatherList)) {
                            String gatherIds = buildingGatherList.stream().map(BuildingGather::getId).collect(Collectors.joining(","));
                            proofread.setGatherId(gatherIds);
                        }
                        proofread.setCity(buildingGaode.getRegionCity());
                        proofread.setDistrict(buildingGaode.getRegionDistricts());
                        proofread.setGridName(buildingGaode.getGridName());
                        proofread.setGaodeId(buildingGaode.getId());
                        proofread.setCreateTime(date);
                        proofread.setUpdateTime(date);
                        proofreadList.add(proofread);
                    }
                    proofreadService.saveBatch(proofreadList);
                    proofreadList.clear();
                });
            }
        });
        log.debug("楼宇勘误数据初始化完毕");
    }
}
